package bhbt.utils;

import java.math.BigDecimal;
import java.util.Random;

public class NumUtil {
	
	/**
	 * 提供精确的乘法运算
	 * @param v1
	 * @param v2
	 * @return 两个参数的数学积
	 */
	public static BigDecimal multiply(String v1, String v2, int scale) {
		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		BigDecimal ret = b1.multiply(b2);
		return round(ret.toString(), scale, BigDecimal.ROUND_HALF_EVEN);
	}
	
	/**
	 * 计算两个数的百分比
	 * @param n1
	 * @param n2
	 * @param scale
	 * @return
	 */
	public static String mathRate(String n1, String n2, int scale){
		BigDecimal ret = divide(n1, n2, scale+2, BigDecimal.ROUND_HALF_EVEN);
		ret = multiply(ret.toString(), String.valueOf(100), scale);
		return ret.toString() + "%";
	}
	
	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指
	 * 定精度，以后的数字四舍五入。舍入模式采用用户指定舍入模式
	 * @param v1
	 * @param v2
	 * @param scale
	 *            表示需要精确到小数点以后几位
	 * @param round_mode
	 *            表示用户指定的舍入模式
	 * @return 两个参数的商
	 */
	public static BigDecimal divide(String v1, String v2, int scale) {
		if(null==v1 || "".equals(v1) || null==v2 || "".equals(v2) || "0".equals(v2)){
			return round("0",scale,BigDecimal.ROUND_HALF_EVEN);
		}
		return divide(v1, v2, scale, BigDecimal.ROUND_HALF_EVEN);
	}
	
	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指
	 * 定精度，以后的数字四舍五入。舍入模式采用用户指定舍入模式
	 * @param v1
	 * @param v2
	 * @param scale
	 *            表示需要精确到小数点以后几位
	 * @param round_mode
	 *            表示用户指定的舍入模式
	 * @return 两个参数的商
	 */
	public static BigDecimal divide(String v1, String v2, int scale, int round_mode) {
		if(null==v1 || "".equals(v1) || null==v2 || "".equals(v2) || "0".equals(v2)){
			return round("0",scale,round_mode);
		}
		try {
			BigDecimal b1 = new BigDecimal(v1);
			BigDecimal b2 = new BigDecimal(v2);
			return b1.divide(b2, scale, round_mode);
		} catch (ArithmeticException e) {
			e.printStackTrace();
		}
		return new BigDecimal("0");
	}
	
	/**
	 * 提供精确的小数位四舍五入处理
	 * @param v
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @param round_mode
	 *            指定的舍入模式
	 * @return 四舍五入后的结果
	 */
	public static BigDecimal round(String v, int scale, int round_mode) {
		BigDecimal b = new BigDecimal(v);
		return b.setScale(scale, round_mode);
	}
	
    /** 
     * 随机指定范围内N个不重复的数 
     * 在初始化的无重复待选数组中随机产生一个数放入结果中， 
     * 将待选数组被随机到的数，用待选数组(len-1)下标对应的数替换 
     * 然后从len-2里随机产生下一个随机数，如此类推 
     * @param max  指定范围最大值 
     * @param min  指定范围最小值 
     * @param n  随机数个数 
     * @return int[] 随机数结果集 
     */  
	public static int[] randomArray(int min, int max, int n) {
		int len = max - min + 1;
		if (max < min || n > len) {
			return null;
		}
		// 初始化给定范围的待选数组
		int[] source = new int[len];
		for (int i = min; i < min + len; i++) {
			source[i - min] = i;
		}
		int[] result = new int[n];
		Random rd = new Random();
		int index = 0;
		for (int i = 0; i < result.length; i++) {
			// 待选数组0到(len-2)随机一个下标
			index = Math.abs(rd.nextInt() % len--);
			// 将随机到的数放入结果集
			result[i] = source[index];
			// 将待选数组中被随机到的数，用待选数组(len-1)下标对应的数替换
			source[index] = source[len];
		}
		return result;
	}

}
